package com.xinzhitong.www.utils;

import com.aliyun.oss.*;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PolicyConditions;
import com.xinzhitong.www.exception.BusyException;
import lombok.Data;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;

/**
 * 文件存取工具
 *
 * @author 徐鑫  吴展鹏
 */
public class FileHelper {

    /**
     * 文件url
     */
    public static String fileURL;

    private static final String TREATY = "http";
    private static final Integer PORT = 8075;

    /**
     * 服务器url
     */
    public static String serverURL = TREATY + "://47.101.180.43" + ":" + PORT;

    static {
        //初始化服务器地址及端口号
        fileURL = "http://xinzhitong.oss-cn-shanghai.aliyuncs.com";
    }

    /**
     * 将文件转储到其他路径
     *
     * @param path 路径
     * @param file 多块文件
     * @throws IOException 文件存取异常
     */
    public static void saveToDontUseIt(String path, MultipartFile file) throws IOException {
        ClassLoader classLoader = FileHelper.class.getClassLoader();
        URL url = classLoader.getResource("");
        assert url != null;
        File tmp = new File(url.getFile() + path);
        File parent = tmp.getParentFile();

        //res用于判断是否成功，以此来决定是否抛出IO异常
        boolean res = true;
        //若父层文件夹不存在，则创建文件夹
        if (!parent.exists())
            res = parent.mkdirs();
        if (!res)
            throw new BusyException();
        //若原文件已经存在，则删除文件
        if (tmp.exists())
            res = tmp.delete();
        if (!res)
            throw new BusyException();
        //创建文件
        res = tmp.createNewFile();
        if (!res)
            throw new BusyException();
        FileCopyUtils.copy(
                file.getInputStream(),
                new FileOutputStream(tmp)
        );
    }

    /**
     * 将文件转储到OSS
     *
     * @param path 路径
     * @param file 多块文件
     * @throws IOException 文件存取异常
     */
    public static void saveTo(String path, MultipartFile file) throws IOException {
        if (path.charAt(0) == '/')
            path = path.replaceFirst("/", "");
        OSSConfig ossConfig = new OSSConfig();
        PropertiesHelper.getFromPropertiesFile("OSS.properties", ossConfig);
        OSS client = new OSSClientBuilder().build(
                ossConfig.getEndpoint(),
                ossConfig.getAccessKeyId(),
                ossConfig.getAccessKeySecret()
        );

        try {
            client.putObject(ossConfig.getBucketName(), path, file.getInputStream());
            System.out.println("Creating an empty folder " + path + "\n");
            OSSObject object = client.getObject(ossConfig.getBucketName(), path);
            System.out.println("Size of the empty folder '" + object.getKey() + "' is " +
                    object.getObjectMetadata().getContentLength());
            object.getObjectContent().close();
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message: " + oe.getErrorCode());
            System.out.println("Error Code:       " + oe.getErrorCode());
            System.out.println("Request ID:      " + oe.getRequestId());
            System.out.println("Host ID:           " + oe.getHostId());
            throw new BusyException();
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message: " + ce.getMessage());
            throw new BusyException();
        } finally {
            client.shutdown();
        }
    }

    /**
     * @Description 生成签名
     * @Author hzl
     * @Date 2018/11/27
     * @Param [callBack ：要进行回调的参数，传入为空即默认为不进行回调]
     * @Return java.util.HashMap<java.lang.String       java.lang.Object>
     * @author 吴展鹏
     */
    public static HashMap<String, Object> generateSign(String callBack, String dirr,String FileName) throws Exception {
        //获取上传oss需要的基本参数

        OSSConfig ossConfig = new OSSConfig();
        PropertiesHelper.getFromPropertiesFile("OSS.properties", ossConfig);
        String endPoint = ossConfig.getEndpoint();
        String accessKeyId = ossConfig.getAccessKeyId();
        String accessKeySecret = ossConfig.getAccessKeySecret();
        String dir = dirr;
        OSS client = null;
        try {
            //开启OSS客户端
            //client = new OSSClient(endPoint, accessKeyId, accessKeySecret);
            client = new OSSClientBuilder().build(
                    ossConfig.getEndpoint(),
                    ossConfig.getAccessKeyId(),
                    ossConfig.getAccessKeySecret()
            );
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            //生成的到期时间转换位s，并转换为String
            String expire = String.valueOf(expireEndTime / 1000);
            PolicyConditions policyConditions = new PolicyConditions();
            policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConditions.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
            //根据到期时间生成policy
            Date expiration = new Date(expireEndTime);
            String postPolicy = client.generatePostPolicy(expiration, policyConditions);
            //生成signature
            String postSignature = client.calculatePostSignature(postPolicy);
            //对policy进行UTF-8编码后转base64
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            //生成上传文件的文件名
            //String fileName = MyConst.WEB_OSS_FILE + UUID.randomUUID().toString();
            String fileName = FileName;
            //封装生成好的数据进行参数返回
            HashMap<String, Object> respMap = new LinkedHashMap<String, Object>();
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("expire", expire);
            respMap.put("fileName", fileName);
            //callBack不为空时为OSS回调web服务上传
            if (callBack != null && callBack != "") {
                respMap.put("callback", callBack);
            }
            return respMap;
        } catch (Exception e) {
            //log.error("生成OSS上传签名失败：" + e);
            throw new Exception("生成OSS上传签名失败！");
        } finally {
            if (client != null) {
                client.shutdown();
            }
        }
    }

    /**
     * 将文件转储到OSS
     *
     * @param path 路径
     * @param file 多块文件
     * @throws IOException 文件存取异常
     */
    static void saveTo(String path, File file) throws IOException {
        if (path.charAt(0) == '/')
            path = path.replaceFirst("/", "");
        OSSConfig ossConfig = new OSSConfig();
        PropertiesHelper.getFromPropertiesFile("OSS.properties", ossConfig);
        OSS client = new OSSClientBuilder().build(
                ossConfig.getEndpoint(),
                ossConfig.getAccessKeyId(),
                ossConfig.getAccessKeySecret()
        );

        try {
            client.putObject(ossConfig.getBucketName(), path, new FileInputStream(file));
            System.out.println("Creating an empty folder " + path + "\n");
            OSSObject object = client.getObject(ossConfig.getBucketName(), path);
            System.out.println("Size of the empty folder '" + object.getKey() + "' is " +
                    object.getObjectMetadata().getContentLength());
            object.getObjectContent().close();
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message: " + oe.getErrorCode());
            System.out.println("Error Code:       " + oe.getErrorCode());
            System.out.println("Request ID:      " + oe.getRequestId());
            System.out.println("Host ID:           " + oe.getHostId());
            throw new BusyException();
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message: " + ce.getMessage());
            throw new BusyException();
        } finally {
            client.shutdown();
        }
    }


    @Data
    private static class OSSConfig {

        private String endpoint;

        private String accessKeyId;

        private String accessKeySecret;

        private String bucketName;

    }

    @Data
    private static class OSSConfigCopy {

        private String endpoint;

        private String accessKeyId;

        private String accessKeySecret;

        private String bucketName;

        private String productClauseFilePath;

    }

    /**
     * 获取服务器上的字符文件
     * @param url 文件路由
     * @return  字符串
     */
    public static String getOssFile(String url){
        String result = "";
        HttpGet get = new HttpGet(url);
        try{
            CloseableHttpClient httpClient = HttpClients.createDefault();

            HttpResponse response = httpClient.execute(get);
            result = getHttpEntityContent(response);

            if(response.getStatusLine().getStatusCode()!= HttpStatus.SC_OK){
                result = "服务器异常";
            }
        } catch (Exception e){
            System.out.println("请求异常");
            throw new RuntimeException(e);
        } finally{
            get.abort();
        }
        return result;
    }
    public static String getHttpEntityContent(HttpResponse response) throws UnsupportedOperationException, IOException{
        String result = "";
        HttpEntity entity = response.getEntity();
        if(entity != null){
            InputStream in = entity.getContent();
            BufferedReader br = new BufferedReader(new InputStreamReader(in, "utf-8"));
            StringBuilder strber= new StringBuilder();
            String line = null;
            while((line = br.readLine())!=null){
                strber.append(line+'\n');
            }
            br.close();
            in.close();
            result = strber.toString();
        }

        return result;

    }

}
